package lift;

public class LiftMonitor {
	private int here;
	private int next;
	private int[] waitEntry, waitExit;
	private int load;
	private LiftView liftView;
	
	public LiftMonitor(LiftView liftView){
		waitEntry = new int[7];
		waitExit = new int[7];
		this.liftView = liftView;
		this.liftView.drawLift(0, 0);
	}
	
	public synchronized  void addPersonWaiting(int floor){
		waitEntry[floor]++;
		liftView.drawLevel(floor, waitEntry[floor]);
		notifyAll();
	}
	
	public synchronized boolean boardLift(int floor, int destinationFloor){
		while (!(load< 4 && next == here && here == floor)){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		load ++;
		waitExit[destinationFloor]++;
		waitEntry[floor]--;
		liftView.drawLevel(floor, waitEntry[floor]);
		liftView.drawLift(floor, load);
		notifyAll();
		return true;
	}
	
	public synchronized boolean unBoardLift(int destinationFloor){
		
		while(!(here == next && here == destinationFloor)){
			try {
				//System.out.println("load: " + load + " here: " + here + " next: " + next);
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		waitExit[destinationFloor]--;
		load--;
		liftView.drawLift(destinationFloor, load);
		notifyAll();
		return true;
	}
	
	public synchronized void goToFloor(int toFloor){
		while (allQueuesAreEmpty()){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		next = toFloor;
	}
	
	public synchronized void arrivedAtFloor(int destinationFloor){
		here = destinationFloor;
		//notifyAll();
		while (!((load == 4 || (waitEntry[destinationFloor] == 0)) && waitExit[destinationFloor] == 0)){
			notifyAll();
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private boolean allQueuesAreEmpty(){
		for (int i = 0; i < 7 ; i++){
			if (waitEntry[i]>0 || waitExit[i] > 0){
				return false;
			}
		}
		return true;
	}
	
	private boolean waitQueueIsEmpty(){
		for (int i = 0; i < 7 ; i++){
			if (waitEntry[i]>0){
				return false;
			}
		}
		return true;
	}
	
	public int getNextFloor(){
		
		if (load == 4 || waitQueueIsEmpty()){
			int mostWantedFloor = 1;
			for (int i = 0; i < waitExit.length ; i++){
				if (waitExit[i] > waitExit[mostWantedFloor]){
					mostWantedFloor = i;
				}
			}
			
			return mostWantedFloor > here ? here + 1 : here - 1;
		}
		int numberAbove = 0;
		int numberBelow = 0;
		for (int i = here ; i < 7 ; i++){
			numberAbove += waitEntry[i];
		}
		for (int i = 0 ; i < here ; i++){
			numberBelow += waitEntry[i];
		}
		if (numberAbove == 0 && here != 0){
			return here - 1;
		}
		if (numberBelow == 0 && here != 6){
			return here + 1;
		}
		
		if (numberBelow == numberAbove){
			if (here >= 3){
				return here+1;
			} else {
				return here-1;
			}
		}
		return numberBelow >= numberAbove ? here-1 : here+1;
		
	}

}
